package org.destinyshine.cricket.utils;

import java.util.*;

/**
 * Created by destinyliu on 2016/5/1.
 */
public abstract class MultiMap<K, V> {

    private HashMap<K, List<V>> internalMap = new HashMap<K, List<V>>();

    private Class<?> keyType;
    private Class<?> valueType;

    public MultiMap() {
        this((Map) null);
    }

    public MultiMap(Map<K, List<V>> map) {
        if (map != null && map.size() > 0) {
            this.internalMap.putAll(map);
        }
        keyType = ReflectionUtils.getSuperClassGenricType(this.getClass(), 0);
        valueType = ReflectionUtils.getSuperClassGenricType(this.getClass(), 1);
    }

    public V get(K name) {
        List<V> valueList = internalMap.get(name);
        return valueList == null || valueList.isEmpty() ? null : valueList.get(0);
    }

    public List<V> getValues(String name) {
        return internalMap.get(name);
    }

    public V[] getValuesArray(String name) {
        List<V> values = internalMap.get(name);
        return MyCollectionUtils.toArray(internalMap.get(name), valueType);
    }

    public Enumeration<V> getValuesEnumeration(String name) {
        return Collections.enumeration(internalMap.get(name));
    }

    public Enumeration<K> getNamesEnumeration() {
        return Collections.enumeration(internalMap.keySet());
    }

    public Map<K, V[]> getValuesArrayMap() {
        Map<K, V[]> map = new HashMap<>();
        for (Map.Entry<K, List<V>> e : internalMap.entrySet()) {
            V[] valuesAry = MyCollectionUtils.toArray(e.getValue(), valueType);
            map.put(e.getKey(), valuesAry);
        }
        return Collections.unmodifiableMap(map);
    }

    public Map<K, List<V>> unmodifiableInternalMap() {
        return Collections.unmodifiableMap(internalMap);
    }

    public void set(K name, V value) {
        List<V> valueList = new ArrayList<>();
        valueList.add(value);
        internalMap.put(name, valueList);
    }

    public void add(K name, V value) {
        List<V> valueList = internalMap.get(name);
        if (valueList == null) {
            valueList = new ArrayList<>();
            internalMap.put(name, valueList);
        }
        valueList.add(value);
    }

    public void clear() {
        this.internalMap.clear();
    }
}
